package com.jlesbegu.arkanoid;

import android.graphics.Bitmap;
import android.util.Log;

public class Balle {

	private static final float MAX_SPEED = 6.f; 

	private float x;
	private float y;
	private int rayon;
	private float dx;
	public float tmpdx;
	private float dy;
	public float tmpdy;
	private int cptTapOnRateau = 0;
	private int cptTapOnBrique = 0;

	private Bitmap balleBitmap;

	public Balle(int x, int y, int rayon, Bitmap bitmap){
		this.x = x;
		this.y = y;
		this.dx = 0;
		this.dy = 0;
		this.rayon = rayon;
		this.balleBitmap = bitmap;
	}





	public void start(){
		float r = (float) (Math.random()*2);
		this.dx = 1*r;
		this.dy = -3;
	}

	public void update(){
		this.x += this.dx;
		this.y += this.dy;
	}


	public void resolveCollisionWithRateau(int xmin, int xmax, int y){

		if(this.y + this.rayon >= y){
			if(this.x + rayon > xmin && this.x -rayon < xmax){
				/* The ball collides the rateau */				
				this.dy = - this.dy;
				this.y = this.y - this.rayon*2;//Math.round(y -10 + Math.abs(this.dy));
				int signx = 1;
				//int signy = 1;
				if((this.x - xmin) < this.rayon*4){
					if(this.dx < 0){
						this.dx = 1.1f * this.dx;
						signx = -1;
					}else{
						this.dx = - 0.9f * this.dx;
					}
				}
				if((xmax - this.x) < this.rayon*4){
					if(this.dx > 0){
						this.dx = 1.1f * this.dx;
					}else{
						this.dx = - 0.9f * this.dx;
						//signy = -1;
					}
				}
				Log.i("BEFORE NORMALIZATION : ",this.dx+":"+this.dy);
				if(Math.abs(this.dx) > MAX_SPEED) this.dx = MAX_SPEED*signx;
				if(Math.abs(this.dy) > MAX_SPEED) this.dy = -MAX_SPEED;
				Log.i("AFTER NORMALIZATION : ",this.dx+":"+this.dy);

				/* +1 cpt for scoring */
				this.cptTapOnRateau++;

				/* Accelerate speed each time there is a collision with the rateau */				
				int signdx = 1;
				int signdy = 1;
				if(dx < 0) signdx = -1;
				if(dy < 0) signdy = -1;

				float accel = 0.8f;
				float tmpdx = Math.abs(this.dx + signdx * accel);
				float tmpdy = Math.abs(this.dy + signdx * accel);
				if(tmpdx < MAX_SPEED){
					this.dx+=signdx * accel;
				}
				if(tmpdy < MAX_SPEED){
					this.dy+=signdy * accel;
				}
			}
		}


	}

	public boolean resolveCollisionWithBrick(int xLeft, int yTop, int width, int height){
		boolean res = false;
		float thisx = this.x;
		float thisy = this.y;

		if(thisx + rayon/2 >= xLeft && thisx -rayon/2 <= xLeft+width){
			if(thisy +rayon/2 >= yTop && thisy -rayon/2 <=yTop+height){
				res = true;
				this.cptTapOnBrique++;
				/* panneau gauche */
				double dgauche = computeDistance(xLeft, yTop, xLeft, yTop+height, thisx, thisy);
				/* panneau haut */
				double dhaut = computeDistance(xLeft, yTop, xLeft+width, yTop, thisx, thisy);
				/* panneau droite */
				double ddroite = computeDistance(xLeft+width, yTop, xLeft+width, yTop+height, thisx, thisy);
				/* panneau dbas */
				double dbas = computeDistance(xLeft, yTop+height, xLeft+width, yTop+height, thisx, thisy);

				//Log.i("Distances ----------------------", ""+dgauche+" : "+dhaut+" : "+ddroite+" : "+dbas);

				//				if(dgauche<EPSILON || ddroite<EPSILON){
				//					res = true;
				//					cptTapOnBrique++;
				//					this.dx = - this.dx;
				//				}
				//				
				//				if(dhaut<EPSILON || dbas<EPSILON){
				//					res = true;
				//					cptTapOnBrique++;
				//					this.dy = - this.dy;
				//				}



				int min = minOf4(dgauche, dhaut, ddroite, dbas);

				//Log.i("Min -------------------", ""+min);

				if(min == 1 || min == 3){
					this.dx = - this.dx;
				}
				if(min == 2 || min == 4){
					this.dy = -this.dy;
				}



			}
		}

		return res;
	}


	public int minOf4(double gauche, double haut, double droite, double bas){
		int res =  0;
		if(gauche <= haut && gauche <= droite && gauche <= bas) return 1;
		if(haut <= gauche && haut <= droite && haut <= bas) return 2;
		if(droite < gauche && droite < haut && droite < bas) return 3;
		if(bas <= gauche && bas <= haut && bas <= droite) return 4;

		return res;
	}

	public double computeDistance(int p1x, int p1y, int p2x, int p2y, float thisx, float thisy){
		double res = 0;

		/* Calcul H projete orthogonal de la balle sur la droite (p1, p2) */
		float hx = 0.f;
		float hy = 0.f;

		/* calcul de l'equation y=ax + b */
		int a;
		int b;
		
		if(p1x == p2x){
			hx = p1x;
			hy = thisy;
			
			
		}else if(p1y == p2y){
			hx = thisx;
			hy = p1y;
		}
		
		
		double PH = computeDistance2Points(hx, hy, thisx, thisy);
		double PA = computeDistance2Points(p1x, p1y, thisx, thisy);
		double PB = computeDistance2Points(p2x, p2y, thisx, thisy);
		
		//Log.i("PH, PA, PB : ", ""+PH+" : "+PA+" : "+PB);
		
		int min = minOf4(PH, PA, PB, Double.MAX_VALUE);
		if(min == 1){
			return PH;
		}else if(min == 2){
			return PA;
		}else if(min == 3){
			return PB;
		}
		
		//		float a;
		//		if(p2x == p1x) {
		//			a = 0;
		//		}else{
		//			a = (p2y-p1y) / (p2x-p1x);
		//		}
		//		float b = p1y - a*p1x;
		//
		//		res = ((a * thisx) - thisy +b) / (Math.sqrt(a*a + 1)); 
		//
		return Math.abs(res);
	}

	
	private double computeDistance2Points(float p1x, float p1y, float p2x, float p2y){
		
		return Math.sqrt(Math.pow(p2x-p1x,2) + Math.pow((p2y-p1y), 2));

	}
	
	public boolean  resolveCollisionWithBounds(int xmax, int ymax) {

		boolean res = false;
		final float x = this.x;
		final float y = this.y;

		//		
		if (x > xmax) {
			this.x = Math.round(xmax-this.dx);
			this.dx = -dx;
		} else if (x < 0) {
			this.x = Math.round(0 +Math.abs(dx));
			this.dx = -this.dx;

		}
		if (y > ymax) {
			this.dy=0;
			this.dx = 0;
			this.y = ymax;

			res = true;
			//this.y = ymax-this.dy;
			//this.dy = -this.dy;

		} else if (y < 0) {
			this.y = Math.round(0+ Math.abs(dy));
			this.dy = -this.dy;
		}

		return res;
	}






	/* GETTERS SETTERS */


	public float getX() {
		return x;
	}


	public void setX(int x) {
		this.x = x;
	}


	public float getY() {
		return y;
	}


	public void setY(int y) {
		this.y = y;
	}


	public float getDx() {
		return dx;
	}


	public void setDx(float dx) {
		this.dx = dx;
	}


	public float getDy() {
		return dy;
	}


	public void setDy(float dy) {
		this.dy = dy;
	}

	public Bitmap getBalleBitmap() {
		return balleBitmap;
	}


	public void setBalleBitmap(Bitmap balleBitmap) {
		this.balleBitmap = balleBitmap;
	}





	public int getRayon() {
		return rayon;
	}





	public void setRayon(int rayon) {
		this.rayon = rayon;
		int diam = rayon*2;

		this.balleBitmap = Bitmap.createScaledBitmap(this.balleBitmap, diam, diam, true);


	}





	public int getCptTapOnRateau() {
		return cptTapOnRateau;
	}





	public void setCptTapOnRateau(int cptTapOnRateau) {
		this.cptTapOnRateau = cptTapOnRateau;
	}


	public long getScore(){
		return cptTapOnRateau + Math.round(cptTapOnRateau*Math.log(cptTapOnRateau)) + cptTapOnBrique*10;
	}



}
